package com.unis.iptv.common.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.unis.iptv.client.RetryHandler;

/**
 * @date Aug 2, 2012
 * @author 杨飞宇
 */
public class AuthenticationBaseNJNewIPTV {
	static String AuthServer = "http://58.223.251.139:8298/auth";
	static String StbId = "C01001990070119000014C09B4E8A8C0";
	// 02584631592的STBID
	// String StbId = "0010019900E06000SY02000AC2D44C8F";
	static String MacAddr = "4C:09:B4:E8:A8:C0";
	// 02584631592的STBID
	// String MacAddr = "00:0A:C2:D4:4C:8F";
	static String IpAddr = "192.168.0.161";
	// String UserId = "025201133801";
	// String Password = "112233";
	static String UserId = "02584631590";
	static String Password = "84631590";
	static final String HostUri = "(http://[^/]*)/";
	static final String MainWin = "<frame name=\"mainWin\" src=\"([^\"]*)\"";
	static final String Action = "<form\\s.*action=[\"']([^ ]*)[\"']\\s.*>";
	static final String Input = "<input\\stype=[\"'][^>]*[\"']\\sname=[\"']([^>]*)[\"']\\svalue=[\"']([^>]*)[\"'\\s*]>";
	static final String HeaderUri = "(http://.*/)[^/]*";
	static final String Location = "\\.location\\s*=\\s*'(.*)';";
	static final String AuthInfo = "Authentication.CTCGetAuthInfo\\('(\\d+)'\\)";
	// 表单提交时空值对应值
	static final Map<String, String> keyValue = new HashMap<String, String>();
	static DefaultHttpClient httpClient;
	static String tempHeaderUri;
	
	public static void main(String[] args) throws Exception {
		// String a = "ChannelID=\"ch09050909510015486077\"";
		// System.out.println(a.indexOf("="));
		// 1 大光路新IPTV(内网专线访问) 2 监测台新IPTV(外网) 3 监测台老IPTV(外网)
		header(4);
		auth();
		// auth2();
	}
	
	static void header(int i) {
		if (i == 1) {
			// 02584631592的STBID
			// String StbId = "0010019900E06000SY02000AC2D44C8F";
			// 02584631592的STBID
			// String MacAddr = "00:0A:C2:D4:4C:8F";
			UserId = "025201133801";
			Password = "112233";
		} else if (i == 2) {
			StbId = "0010019900E06000SY02000AC2D44C8F";
			MacAddr = "00:0A:C2:D4:4C:8F";
			UserId = "02584631592";
			Password = "84631592";
		} else if (i == 3) {
			UserId = "02584631590";
			Password = "84631590";
		} else if (i == 4) {
			AuthServer = "http://222.246.132.231:8298/auth";
			MacAddr = "B0:75:D5:9A:BF:DB";
			StbId = "00100199007011400002B075D59ABFDB";
			UserId = "073128537696@VOD";
			Password = "594208837";
		}
	}
	
	static void auth2() throws Exception {
	}
	
	static void auth() throws Exception {
		String url;
		String location;
		String content;
		ClientConnectionManager cm = new ThreadSafeClientConnManager();
		httpClient = new DefaultHttpClient(cm);
		httpClient.setHttpRequestRetryHandler(new RetryHandler());
		// auth
		url = AuthServer + "?UserID=" + UserId + "&Action=Login";
		content = Content(url);
		keyValue.put(
				"Authenticator",
				Authenticator(Matcher(content, AuthInfo), StbId, MacAddr,
						IpAddr, UserId, Password));
		keyValue.put("AccessMethod", "dhcp");
		keyValue.put("AccessUserName", UserId);
		content = Content(Matcher(AuthServer, HeaderUri, content, Action),
				Form(content, keyValue));
		location = Matcher(content, Location);
		content = Content(Matcher(AuthServer, HostUri) + "/" + location);
		location = Matcher(content, Location);
		
		content = Content(AuthServer.substring(0, AuthServer.lastIndexOf('/'))
				+ "/" + location);
		location = Matcher(content, Location).replace(" ", "%20");
		content = Content(location);
		location = Matcher(content, Location);
		content = Content(location);
		content = Content(tempHeaderUri + Matcher(content, Action),
				Form(content));
		
		content = Content(tempHeaderUri + Matcher(content, Location));
		// ChannelList
		content = Content(tempHeaderUri + Matcher(content, Action),
				Form(content));
		DataList(content, null, null);
		content = Content(Matcher(content, HostUri, MainWin));
		// System.out.println(content);
		// SaveHtml.saveHtml(content);
		
	}
	
	static Map<String, String> DataList(String input, String regex,
			String splitRegex) {
		
		Map<String, String> dataList = new HashMap<String, String>();
		regex = "Authentication\\.CTCSetConfig\\('Channel', '(.*)'\\);";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(input);
		if (m.find()) {
			String group[] = m.group(1).split(",");
			for (String string : group) {
				
				System.out.println(string);
			}
		}
		return null;
	}
	
	static String Matcher(String input, String regex) {
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(input);
		if (m.find())
			return m.group(1);
		return "";
	}
	
	static String Matcher(String input, String firstRegex, String secondRegex) {
		return Matcher(input, firstRegex, input, secondRegex);
	}
	
	static String Matcher(String firstInput, String firstRegex,
			String secondInput, String secondRegex) {
		StringBuffer matcher = new StringBuffer();
		matcher.append(Matcher(firstInput, firstRegex)).append(
				Matcher(secondInput, secondRegex));
		return matcher.toString();
	}
	
	static Map<String, String> Form(String content, Map<String, String> keyValue) {
		Map<String, String> basicNameValuePairs = new HashMap<String, String>();
		Pattern pattern = Pattern.compile(Input);
		Matcher matcher = pattern.matcher(content);
		while (matcher.find()) {
			String key = matcher.group(1);
			String value = matcher.group(2);
			if (value == null || value.equals(""))
				value = keyValue.get(key);
			basicNameValuePairs.put(key, value);
		}
		return basicNameValuePairs;
	}
	
	static Map<String, String> Form(String content) {
		Map<String, String> basicNameValuePairs = new HashMap<String, String>();
		Pattern pattern = Pattern.compile(Input);
		Matcher matcher = pattern.matcher(content);
		while (matcher.find()) {
			String key = matcher.group(1);
			String value = matcher.group(2);
			basicNameValuePairs.put(key, value);
		}
		return basicNameValuePairs;
	}
	
	static String get(String key) {
		
		return null;
	}
	
	static String Content(String url) {
		tempHeaderUri = Matcher(url, HeaderUri);
		HttpGet httpGet = new HttpGet(url);
		System.out.println("executing get request " + httpGet.getURI());
		try {
			HttpResponse httpResponse = httpClient.execute(httpGet);
			HttpEntity entity = httpResponse.getEntity();
			System.out.println("----------------------------------------");
			System.out.println(httpResponse.getStatusLine());
			if (entity != null) {
				System.out.println("Response content length: "
						+ entity.getContentLength());
			}
			System.out.println("----------------------------------------");
			String content = EntityUtils.toString(entity, "GBK");
			httpGet.abort();
			return content;
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	static String Content(String url, Map<String, String> basicNameValuePairs) {
		HttpPost httpost = new HttpPost(url);
		System.out.println("executing post request " + httpost.getURI());
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		for (String key : basicNameValuePairs.keySet()) {
			nvps.add(new BasicNameValuePair(key, basicNameValuePairs.get(key)));
		}
		try {
			httpost.setEntity(new UrlEncodedFormEntity(nvps, "GBK"));
			basicNameValuePairs.clear();
			nvps.clear();
			HttpResponse response = httpClient.execute(httpost);
			System.out.println("----------------------------------------");
			System.out.println(response.getStatusLine());
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
				return Content(response.getFirstHeader("Location").getValue());
			} else {
				HttpEntity entity = response.getEntity();
				String content = EntityUtils.toString(entity, "GBK");
				httpost.abort();
				return content;
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	static String CTCSetConfig(String content, String Name) {
		int Begin, End;
		String Key = "Authentication.CTCSetConfig ('" + Name + "','";
		Begin = content.indexOf(Key);
		if (Begin > 0) {
			Begin += Key.length();
			End = content.indexOf("'", Begin);
			if (End > 0)
				return content.substring(Begin, End);
		}
		return "";
	}
	
	static public String Authenticator(String AuthInfo, String StbId,
			String MacAddr, String IpAddr, String UserId, String Password) {
		String AuthStr = "";
		String Result = "";
		Random Rand = new Random(Calendar.getInstance().getTimeInMillis());
		AuthStr += String.format("%08d", Rand.nextInt(100000000)) + "$";
		AuthStr += AuthInfo + "$";
		AuthStr += UserId + "$";
		AuthStr += StbId + "$";
		AuthStr += IpAddr + "$";
		AuthStr += MacAddr + "$";
		AuthStr += "990070|$CTC";
		try {
			byte Auth[] = AuthStr.getBytes("ASCII");
			int Len = Auth.length;
			int Mod = Len % 8;
			
			if (Mod != 0)
				Len += 8 - Mod;
			byte AuthBytes[] = new byte[Len];
			
			for (int i = 0; i < Len; i++) {
				if (i >= Auth.length)
					AuthBytes[i] = (byte) (8 - Mod);
				else
					AuthBytes[i] = Auth[i];
			}
			
			String Algorithm = "DESede";
			byte KeyBytes[] = new byte[24];
			byte PassBytes[] = Password.getBytes();
			
			for (int i = 0; i < 24; i++) {
				if (i < PassBytes.length)
					KeyBytes[i] = PassBytes[i];
				else
					KeyBytes[i] = 0x30;
			}
			Security.addProvider(new com.sun.crypto.provider.SunJCE());
			SecretKey DesKey = new SecretKeySpec(KeyBytes, Algorithm);
			Cipher C = Cipher.getInstance(Algorithm);
			C.init(Cipher.ENCRYPT_MODE, DesKey);
			byte Encrypt[] = C.doFinal(AuthBytes);
			for (int i = 0; i < Len; i++) {
				Result += String.format("%02X",
						Encrypt[i] < 0 ? (256 + Encrypt[i]) : Encrypt[i]);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Result;
	}
}
